
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;



/*@Uses:
 * 1. Program Used to calulate MAP METRICS.
 * 2. Rank of retrived result.
 *
 * @dependency:
 * 
 * @SET
 * 1. SCORE TABLE
 * 2. sum
 * 3. desired_rank
 * 4. Recall value
 * 5. Table:(bug_map_at_Nr)
 * */
public class a_MAP_and_RANK 
{
	public Connection conn =  null;
	public String dbname="2apache";
	public String userid="root";
	public String passwd = "123";
	public ArrayList<String> bugids =  null;
	
	public String score_table = "a_h7_score";
	public String sum = "sum1";
	public int desired_rank  = 5;
	public int Nr = 10;
	
	
public void process(Connection conn)
{
		a_h1_1_accuracy a_h1_1 =  new a_h1_1_accuracy();
		
		bugids =  new ArrayList<String>();
		bugids =  a_h1_1.get_bugids(conn,bugids,score_table);
		System.out.println("No Of bugids = "+bugids.size());
		    
		int No_of_bugids = 0; 
		utility u =  new utility();   
		
		double map = 0;
		double map_at_Nr=0;
		double recall_at_Nr=0;
		int bug_pass_desired_rank=0;
		
		for(int i =0;i<bugids.size();i++)
		  {
			  
			   System.out.println("+++++++++++++++++++++++++++++++++++++++");
			   String bugid = bugids.get(i);
			   String bug_version_table  =  a_h1_1.get_table(conn,bugid,score_table);		 
			   System.out.println("Bugid = "+bugid +" table="+bug_version_table);
			   ArrayList<String> bug_valid_svn_file = a_h1_1.get_bug_svn_valid_files(conn,bugid,bug_version_table);
			   
			   
			   if(bug_valid_svn_file.size()!=0)
			   {			   
				   No_of_bugids++;
				   ArrayList<file_and_rank> ranked_table_files = u.get_ranked_files(bugid, conn, score_table, sum);
				   ArrayList<file_and_rank> ranked_bug_files = u.get_ranked_bug_files(ranked_table_files,bug_valid_svn_file);
				   System.out.println("Size ="+ranked_bug_files.size());
				   u.print(ranked_bug_files,bugid);
				   double bug_map = calculate_map(ranked_bug_files);
				   map=map+bug_map;
				   
				   boolean have_desired_rank =check_desired_rank(ranked_bug_files);
				   if(have_desired_rank)
				   {
					   bug_pass_desired_rank++;
					   System.out.println("Bug Id[PASS]"+bugid);
				   }
				   
				  double temp_bug_map_at_Nr = calculate_bug_map_at_Nr(ranked_bug_files,Nr);
				  double temp_bug_recall_at_Nr=calculate_bug_recall_at_Nr(ranked_bug_files,Nr);
				  recall_at_Nr = recall_at_Nr+temp_bug_recall_at_Nr;
				  map_at_Nr=map_at_Nr + temp_bug_map_at_Nr;
				  insert_to_bug_map_at_Nr(bugid, ranked_bug_files,bug_map,temp_bug_map_at_Nr,temp_bug_recall_at_Nr, conn);
				   
			   }
			  
			  System.out.println("++++++++++++++++++++++++++++++++++++++"); 
			 
		   }//for	
		
		map =  map/No_of_bugids;
		map_at_Nr = map_at_Nr/No_of_bugids;
		recall_at_Nr =  recall_at_Nr/No_of_bugids;
		
		System.out.println("Final map="+map);
		System.out.println("Final Map @Nr("+Nr+")="+map_at_Nr);
		System.out.println("Final Recall="+recall_at_Nr);
		System.out.println("bug satisfy desired rank[rank of retived files]="+bug_pass_desired_rank);		
		
	    System.out.println("Valid bug ids ="+No_of_bugids);	
}


private double calculate_bug_recall_at_Nr( ArrayList<file_and_rank> ranked_bug_files, int Nr)
{
	double recall = 0.0;
	int No_of_files_ret = 0;
	for(int i=0;i<ranked_bug_files.size();i++)
	 {
		int file_rank = ranked_bug_files.get(i).rank;
		if(file_rank<=Nr)
		{
			No_of_files_ret++;
		}
	 }
	
	recall = (No_of_files_ret*1.0)/ranked_bug_files.size();
	System.out.println("Recall = "+recall);
	return recall;
}


/*1. Ranked Bug Files
 *2. bug_map
 *3. map_at_Nr 
 * */
public void insert_to_bug_map_at_Nr(String bugid, ArrayList<file_and_rank> ranked_bug_files
		                            ,double bug_map,double map_at_Nr,double recall_at_Nr,
		                             Connection conn2) 
{
	
	Statement stmt=null;
	
	String ranks_concat = "";
	for(int i=0;i<ranked_bug_files.size();i++)
	{
		int rank = ranked_bug_files.get(i).rank;
		ranks_concat = ranks_concat+rank+",";
	}
	
	String ins_q = "insert into a_bug_map_and_recall_at_Nr values('"+bugid+"','"+ranks_concat+"',"+bug_map+","+map_at_Nr+","+recall_at_Nr+")";
	
	try
	{
		stmt =  conn.createStatement();
		stmt.execute(ins_q);
		
		if(stmt!=null)
			stmt.close();
	} catch (SQLException e) 
	{ 	e.printStackTrace(); }
	
}

// Calculating map at multiple Nr points	
private double calculate_bug_map_at_Nr(ArrayList<file_and_rank> ranked_bug_files, int nr) 
{
	int No_of_files_nr_rank = 0;
	
	for(int i=0;i<ranked_bug_files.size();i++)
	{
	    int file_rank=ranked_bug_files.get(i).rank;
		
		if(file_rank<=nr)
		{
		  No_of_files_nr_rank++;	
		  System.out.println("File rank="+file_rank);
		}
		
	}
	
	double bug_map_at_Nr = (No_of_files_nr_rank*1.0)/nr;
	System.out.println("@Nr="+nr+" bug_map@Nr="+bug_map_at_Nr);
	
	return bug_map_at_Nr;
	
}//


//Rank Metrics	
private boolean check_desired_rank(ArrayList<file_and_rank> ranked_bug_files) 
{
	boolean contain_desired_rank = false;
	
	for(int i=0;i<ranked_bug_files.size();i++)
	{
		int rank = ranked_bug_files.get(i).rank;
		if(rank<=desired_rank)
		{
			contain_desired_rank = true;
			break;
		}
		
	}//for

	return contain_desired_rank;
}

//MAP metic at each recall point
//sorted rank
public double calculate_map(ArrayList<file_and_rank> ranked_bug_files)
{
	double bug_map = 0;
	for(int i=0;i<ranked_bug_files.size();i++)
	{
		int rank = ranked_bug_files.get(i).rank;
		String file = ranked_bug_files.get(i).file_name;
		double precision = ((i+1)*1.0)/rank;
		System.out.println("i+1="+(i+1)+" rank="+rank+" file="+file+" precision="+precision);
		bug_map +=precision;
	}
	
	double avg_bug_map = (bug_map/ranked_bug_files.size());
	
	System.out.println("Avg bug_map="+avg_bug_map);
	//intr();
    return avg_bug_map;
}//map


public void intr()
{
  
	BufferedReader br  = new BufferedReader(new InputStreamReader(System.in));
	try
     {
		System.out.println("Enter");
		br.readLine();
		
		
	  } catch (IOException e) 
	  {
		
		e.printStackTrace();
	  }

}

public static void main(String args[])
{
	  a_MAP_and_RANK a_map = new a_MAP_and_RANK();
	  db_conn db =  new db_conn();
	  a_map.conn = db.connect(a_map.dbname, a_map.userid, a_map.passwd);
	  a_map.process(a_map.conn);
	  db.close(db.conn);	  
	  
	}//main
	
}//class
